package com.dongjiantong.common.redis;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * Created by cao on 2017/10/29.
 */
public class ObjectUtil {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    /**
     * 构造方法私有不可创建对象
     */
    private ObjectUtil(){

    }

    /**
     * 对象转字符串
     * @param obj
     * @return
     */
    public static String objectToJsonStr(Object obj)
    {
        Gson gson = new Gson();
        return gson.toJson(obj);
    }

    public static <T extends Serializable> T jsonToMap(String result) throws Exception
    {
       // Gson gson = new Gson();
        //return  gson.fromJson(result, type);
        /**
         * 重写map的反序列化
         */
        Gson gson = new GsonBuilder().registerTypeAdapter(new TypeToken<Map<String, Object>>() {
                }.getType(), new MapTypeAdapter()).create();
//MapTypeAdapter是继承了TypeAdapter类，并单独处理Map类型的反序列化。注意：目前只绑定了Map类型，其子类（HashMap）的处理没有变化。
        return gson.fromJson(result,  new TypeToken<Map<String, Object>>() {
        }.getType());
    }

    public static <T extends Serializable> T jsonToObject(String result,Class<T> type) throws Exception
    {
        Gson gson = new Gson();
        T object = gson.fromJson(result, type);
        return object;

    }
    public static <T extends Serializable> T jsonToList(String result) throws Exception
    {
        Gson gson = new Gson();

        return gson.fromJson(result,
                new TypeToken<List<T>>() {
                }.getType());
    }

    public static byte[] jsonSerialize(Object obj)
    {
        return JSON.toJSONString(obj, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }
    public static <T extends Serializable> T jsonDeserialize(byte[] bytes) throws Exception
    {
       // Class<T> clazz//
        String str = new String(bytes, DEFAULT_CHARSET);

        return (T) JSON.parseObject(str, Object.class);
    }

    /**
     * 对象序列化(将对象转换成byte[])
     * @param obj
     * @return
     * @throws IOException
     */
    public static byte[] objectToBytes(Object obj) throws Exception{
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        byte[] bytes = null;
        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            bytes = bos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(bos!=null){
                bos.close();
            }
            if(oos!=null){
                oos.close();
            }
        }
        return bytes;
    }
    /**
     * 对象凡序列化(byte[] 转对象)
     * @param bytes
     * @return
     * @throws Exception
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public  static <T extends Serializable> T bytesToObject(byte[] bytes) throws Exception{
        ByteArrayInputStream bis=null;
        ObjectInputStream ois = null;
        T obj=null;
        try {
            //读取字节到内存
            bis = new ByteArrayInputStream(bytes);
            //转换流
            ois = new ObjectInputStream(bis);
            //变成对象
            obj=(T) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(bis!=null){
                bis.close();
            }
            if(ois!=null){
                ois.close();
            }
        }
        return obj;
    }



    public static class MapTypeAdapter extends TypeAdapter<Object> {

        @Override
        public Object read(JsonReader in) throws IOException {
            JsonToken token = in.peek();
            switch (token) {
                case BEGIN_ARRAY:
                    List<Object> list = Lists.newArrayList();
                    in.beginArray();
                    while (in.hasNext()) {
                        list.add(read(in));
                    }
                    in.endArray();
                    return list;

                case BEGIN_OBJECT:
                    Map<String, Object> map = Maps.newLinkedHashMap();
                    in.beginObject();
                    while (in.hasNext()) {
                        map.put(in.nextName(), read(in));
                    }
                    in.endObject();
                    return map;

                case STRING:
                    return in.nextString();

                case NUMBER:
                    /**
                     * 改写数字的处理逻辑，将数字值分为整型与浮点型。
                     */
                    double dbNum = in.nextDouble();

                    // 数字超过long的最大值，返回浮点类型
                    if (dbNum > Long.MAX_VALUE) {
                        return dbNum;
                    }

                    // 判断数字是否为整数值
                    long lngNum = (long) dbNum;
                    if (dbNum == lngNum) {
                        return lngNum;
                    } else {
                        return dbNum;
                    }

                case BOOLEAN:
                    return in.nextBoolean();

                case NULL:
                    in.nextNull();
                    return null;

                default:
                    throw new IllegalStateException();
            }
        }

        @Override
        public void write(JsonWriter out, Object value) throws IOException {
            // 序列化无需实现
        }

    }
}
